<?php

/* * 
 * 项目扩展函数库
 */

/**
 * FirePHP调试类
 * @param string $key
 * @param string $value
 */
function console($key, $value = null) {
    $arg = func_get_args();
    if (count($arg) == 1) {
        FB::info($key, $value);
    } else {
        FB::info($value, $key);
    }
}

/**
 * 字符截取 支持UTF8/GBK
 * @param $string
 * @param $length
 * @param $dot
 */
function str_cut($string, $length, $dot = '...') {
    $strlen = strlen($string);
    if ($strlen <= $length)
        return $string;
    $string = str_replace(array(' ', '&nbsp;', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'), array('∵', ' ', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'), $string);
    $strcut = '';
    if (strtolower(C("DEFAULT_CHARSET")) == 'utf-8') {
        $length = intval($length - strlen($dot) - $length / 3);
        $n      = $tn     = $noc    = 0;
        while ($n < strlen($string)) {
            $t = ord($string[$n]);
            if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
                $tn = 1;
                $n++;
                $noc++;
            } elseif (194 <= $t && $t <= 223) {
                $tn = 2;
                $n += 2;
                $noc += 2;
            } elseif (224 <= $t && $t <= 239) {
                $tn = 3;
                $n += 3;
                $noc += 2;
            } elseif (240 <= $t && $t <= 247) {
                $tn = 4;
                $n += 4;
                $noc += 2;
            } elseif (248 <= $t && $t <= 251) {
                $tn = 5;
                $n += 5;
                $noc += 2;
            } elseif ($t == 252 || $t == 253) {
                $tn = 6;
                $n += 6;
                $noc += 2;
            } else {
                $n++;
            }
            if ($noc >= $length) {
                break;
            }
        }
        if ($noc > $length) {
            $n -= $tn;
        }
        $strcut = substr($string, 0, $n);
        $strcut = str_replace(array('∵', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'), array(' ', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'), $strcut);
    } else {
        $dotlen      = strlen($dot);
        $maxi        = $length - $dotlen - 1;
        $current_str = '';
        $search_arr  = array('&', ' ', '"', "'", '“', '”', '—', '<', '>', '·', '…', '∵');
        $replace_arr = array('&amp;', '&nbsp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;', ' ');
        $search_flip = array_flip($search_arr);
        for ($i = 0; $i < $maxi; $i++) {
            $current_str = ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
            if (in_array($current_str, $search_arr)) {
                $key         = $search_flip[$current_str];
                $current_str = str_replace($search_arr[$key], $replace_arr[$key], $current_str);
            }
            $strcut .= $current_str;
        }
    }
    return $strcut . $dot;
}

function display($file = '', $templateid = 0, $tpldir = '', $gettplfile = 0, $primaltpl = '') {
    if (0 === strpos($file, 'diy:')) {
        $file = str_replace('diy:', '', $file);
        $pre  = 'diy:';
    } else {
        $pre = '__P__:';
    }
    if ($file == '') {
        $file   = '__PRE____P__/__G__/__M__/__A__';
        $tpldir = '__DIR__/template';
    } else {
        if (0 === strpos($file, '@')) {
            //存在@开头为按照原始的template进行
            $file = str_replace('@', '', $file);
        } else {
            $file     = '__PRE____P__/' . $file;
            $tpldir   = '__DIR__template';
        }
    }
    $addParam = array(
        '__PRE__' => $pre,
        '__DIR__' => PLUGIN_DIR,
        '__P__'   => PLUGIN_NAME
    );
    $file     = format_short_string($file, $addParam);
    $tpldir   = format_short_string($tpldir, $addParam);
    return "include_once template('{$file}', '{$templateid}', '{$tpldir}', '{$gettplfile}', '{$primaltpl}');";
}

function format_short_string($string, $addParam = array()) {
    foreach ($addParam as $key => $value) {
        $string = str_replace($key, $value, $string);
    }
    $string = str_replace('__G__', GROUP_NAME, $string);
    $string = str_replace('__M__', MODULE_NAME, $string);
    $string = str_replace('__A__', ACTION_NAME, $string);
    return $string;
}

/**
 * 格式化整整数 用于判断是否正确
 * @param string $value
 * @return int
 */
function format_int($value) {
    if (preg_match('/^\d+$/', $value, $arr)) {
        return $arr[0];
    } else {
        return 0;
    }
}

/**
 * 格式化商品价格
 *
 * @access  public
 * @param   float   $price  商品价格
 * @return  string
 */
function format_price($price, $multiple = 100) {
    $price = $price / $multiple;
    $price = number_format($price, 2, '.', '');
    return $price;
}

function reStatus($status = false, $msg = '', $data = array()) {
    $return_arr = array(
        'status' => $status,
        'msg'    => $msg,
        'data'   => $data
    );
    return $return_arr;
}

/**
 * 导入Packet中的文件
 * @param string $name 指定路径 如:Class.Service.HelloService
 * @param string $ext 拓展名
 * @return bool 加载成功返回真
 */
function importPacket($name, $ext = '.class.php') {
    return import($name, PACKET_PATH, $ext);
}

/**
 * 加密解密
 * @param type $string 明文 或 密文  
 * @param type $operation DECODE表示解密,其它表示加密  
 * @param type $key 密匙  
 * @param type $expiry 密文有效期  
 * @return string 
 */
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
// 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
    $ckey_length   = 4;
// 密匙
    $key           = md5(($key ? $key : C("AUTHCODE")));
// 密匙a会参与加解密
    $keya          = md5(substr($key, 0, 16));
// 密匙b会用来做数据完整性验证
    $keyb          = md5(substr($key, 16, 16));
// 密匙c用于变化生成的密文
    $keyc          = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
// 参与运算的密匙
    $cryptkey      = $keya . md5($keya . $keyc);
    $key_length    = strlen($cryptkey);
// 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性
// 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确  
    $string        = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
    $string_length = strlen($string);
    $result        = '';
    $box           = range(0, 255);
    $rndkey        = array();
// 产生密匙簿
    for ($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }
// 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
    for ($j = $i          = 0; $i < 256; $i++) {
        $j       = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp     = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }
// 核心加解密部分
    for ($a = $j       = $i       = 0; $i < $string_length; $i++) {
        $a       = ($a + 1) % 256;
        $j       = ($j + $box[$a]) % 256;
        $tmp     = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
// 从密匙簿得出密匙进行异或，再转成字符
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }
    if ($operation == 'DECODE') {
// substr($result, 0, 10) == 0 验证数据有效性
// substr($result, 0, 10) - time() > 0 验证数据有效性  
// substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性  
// 验证数据有效性，请看未加密明文的格式  
        if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
// 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
// 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码  
        return $keyc . str_replace('=', '', base64_encode($result));
    }
}

/*
 * 产生随机字符串 
 * 产生一个指定长度的随机字符串,并返回给用户 
 * @access public 
 * @param int $len 产生字符串的位数 
 * @return string 
 */

function genRandomString($len = 6) {
    $chars = array(
        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
        "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
        "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
        "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
        "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
        "3", "4", "5", "6", "7", "8", "9"
    );
    $charsLen = count($chars) - 1;
    shuffle($chars);    // 将数组打乱 
    $output   = "";
    for ($i = 0; $i < $len; $i++) {
        $output .= $chars[mt_rand(0, $charsLen)];
    }
    return $output;
}

/**
 * 取得文件扩展
 * 
 * @param $filename 文件名
 * @return 扩展名
 */
function fileext($filename) {
    return strtolower(trim(substr(strrchr($filename, '.'), 1, 10)));
}

/**
 * 返回附件类型图标
 * @param $file 附件名称
 * @param $type png为大图标，gif为小图标
 */
function file_icon($file, $type = 'png') {
    $ext_arr = array('doc', 'docx', 'ppt', 'xls', 'txt', 'pdf', 'mdb', 'jpg', 'gif', 'png', 'bmp', 'jpeg', 'rar', 'zip', 'swf', 'flv');
    $ext = fileext($file);
    if ($type == 'png') {
        if ($ext == 'zip' || $ext == 'rar')
            $ext = 'rar';
        elseif ($ext == 'doc' || $ext == 'docx')
            $ext = 'doc';
        elseif ($ext == 'xls' || $ext == 'xlsx')
            $ext = 'xls';
        elseif ($ext == 'ppt' || $ext == 'pptx')
            $ext = 'ppt';
        elseif ($ext == 'flv' || $ext == 'swf' || $ext == 'rm' || $ext == 'rmvb')
            $ext = 'flv';
        else
            $ext = 'do';
    }

    if (in_array($ext, $ext_arr)) {
        return CONFIG_SITEURL . 'static/images/ext/' . $ext . '.' . $type;
    } else {
        return CONFIG_SITEURL . 'static/images/ext/blank.' . $type;
    }
}

/**
 * 判断是否为图片
 */
function is_image($file) {
    $ext_arr = array('jpg', 'gif', 'png', 'bmp', 'jpeg', 'tiff');
    $ext = fileext($file);
    return in_array($ext, $ext_arr) ? $ext_arr : false;
}

/**
 * 调试，用于保存数组到txt文件 正式生产删除 array2file($info, 'post.txt');
 */
function array2file($array, $filename) {
    file_exists($filename) or touch($filename);
    file_put_contents($filename, var_export($array, TRUE));
}

/**
 * 安全过滤函数
 *
 * @param $string
 * @return string
 */
function safe_replace($string) {
    $string = str_replace('%20', '', $string);
    $string = str_replace('%27', '', $string);
    $string = str_replace('%2527', '', $string);
    $string = str_replace('*', '', $string);
    $string = str_replace('"', '&quot;', $string);
    $string = str_replace("'", '', $string);
    $string = str_replace('"', '', $string);
    $string = str_replace(';', '', $string);
    $string = str_replace('<', '&lt;', $string);
    $string = str_replace('>', '&gt;', $string);
    $string = str_replace("{", '', $string);
    $string = str_replace('}', '', $string);
    return $string;
}

/**
 * 返回经stripslashes处理过的字符串或数组
 * @param $string 需要处理的字符串或数组
 * @return mixed
 */
function new_stripslashes($string) {
    if (!is_array($string))
        return stripslashes($string);
    foreach ($string as $key => $val)
        $string[$key] = new_stripslashes($val);
    return $string;
}

/**
 * 返回经addslashes处理过的字符串或数组
 * @param $string 需要处理的字符串或数组
 * @return mixed
 */
function new_addslashes($string) {
    if (!is_array($string))
        return addslashes($string);
    foreach ($string as $key => $val)
        $string[$key] = new_addslashes($val);
    return $string;
}

/**
 * 取得URL地址中域名部分
 * @param type $url 
 * @return \url 返回域名
 */
function urlDomain($url) {
    if (preg_match_all('#https?://(.*?)($|/)#m', $url, $Domain)) {
        return $Domain[0][0];
    }
    return false;
}

/**
 * 获取当前页面完整URL地址
 */
function get_url() {
    $sys_protocal = isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443' ? 'https://' : 'http://';
    $php_self     = $_SERVER['PHP_SELF'] ? safe_replace($_SERVER['PHP_SELF']) : safe_replace($_SERVER['SCRIPT_NAME']);
    $path_info    = isset($_SERVER['PATH_INFO']) ? safe_replace($_SERVER['PATH_INFO']) : '';
    $relate_url   = isset($_SERVER['REQUEST_URI']) ? safe_replace($_SERVER['REQUEST_URI']) : $php_self . (isset($_SERVER['QUERY_STRING']) ? '?' . safe_replace($_SERVER['QUERY_STRING']) : $path_info);
    return $sys_protocal . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') . $relate_url;
}

// 循环创建目录，兼容以前使用mk_dir创建目录的方法。
function mk_dir($dir, $mode = 0777) {
    return mkdir($dir, $mode, true);
}
